﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RzCorportativo.DataAccess;

namespace RzCorportativo.Lib
{
    public class Grupo
    {
        public int GrupoId { get; set; }
        public string Descricao { get; set; }
        private bool ativoChanged;
        private bool ativo;
        public bool Ativo { get { return this.ativo; } set { this.ativo = value; this.ativoChanged = true; } }
        public bool IsNew { get { return this.GrupoId == 0; } }
        public List<Lib.Login> Logins { get; set; }
        public List<ItemSistema> Itens { get; set; }
        private RzCorportativo.DataAccess.Grupo model { get; set; }

        public static Grupo CreateInstance(int grupoId)
        {
            Grupo e = new Grupo();
            RzCorportativo.DataAccess.SistemaCurricularEntities db = new SistemaCurricularEntities();
            var p = db.Grupo.Where(w => w.GrupoId == grupoId).FirstOrDefault();
            if (p != null)
                e = e.CreateGrupo(p);
            return e;
        }

        public List<Lib.Login> ListarLogin(int take, int skype)
        {
            List<Lib.Login> logins = new List<Login>();

            return logins;
        }

        public bool Salvar()
        {
            bool @result = false;
            Transaction.Begin((entity) =>
            {
                if (this.IsNew)
                    this.model = this.Insert(entity);
                else
                    this.model = this.Update(entity);
                return true;
            }).OnError((ex) =>
            {
                @result = false;
                throw ex;
            }).OnSuccess(() =>
            {
                @result = true;
                this.GrupoId = this.model.GrupoId;
            });
            return @result;
        }

        private RzCorportativo.DataAccess.Grupo Insert(SistemaCurricularEntities entity)
        {
            var @item = this.CreateModel(entity);
            entity.AddToGrupo(@item);
            return @item;
        }

        private RzCorportativo.DataAccess.Grupo Update(SistemaCurricularEntities entity)
        {
            var @item = this.CreateModel(entity);
            return @item;
        }

        private RzCorportativo.DataAccess.Grupo CreateModel(SistemaCurricularEntities entity)
        {
            var grupo = new RzCorportativo.DataAccess.Grupo();
            if (!this.IsNew)
            {
                grupo = entity.Grupo.Where(w => w.GrupoId == this.GrupoId).FirstOrDefault();
                if (grupo == null)
                    throw new Exception("Código inválido");
            }
            grupo.GrupoId = this.GrupoId;
            grupo.Descricao = this.Descricao;
            grupo.Ativo = this.ativo;
            return grupo;
        }

        internal Lib.Grupo CreateGrupo(RzCorportativo.DataAccess.Grupo item, bool loadLogin = true)
        {
            Grupo model = new Grupo();
            model.GrupoId = item.GrupoId;
            model.Descricao = item.Descricao;
            model.ativo = item.Ativo;
            model.Logins = new List<Login>();
            if (item.Login != null && loadLogin)
            {
                model.Logins = item.Login.Select(s => new Lib.Login()
                {
                    UsuarioId = s.Usuario.FirstOrDefault() != null ? s.Usuario.FirstOrDefault().UsuarioId : 0,
                    Usuario = new Usuario().Create(s.Usuario.FirstOrDefault()),
                    LoginId = s.LoginId,
                    LoginText = s.Nick
                }).ToList();
            }
            if (item.ItemGrupo != null)
            {
                Lib.ItemSistema itemS = new ItemSistema();
                model.Itens = new List<Lib.ItemSistema>(item.ItemGrupo.Select(s => itemS.Create(s.ItemSistema)).ToList());
            }
            return model;
        }

        public static List<Grupo> Listar(Grupo grupo)
        {
            if (grupo == null)
                grupo = new Grupo();
            List<Grupo> especialidades = new List<Grupo>();
            RzCorportativo.DataAccess.SistemaCurricularEntities db = new SistemaCurricularEntities();
            especialidades = db.Grupo.Where(w =>
                    ((grupo.GrupoId == 0) || (grupo.GrupoId == w.GrupoId)) &&
                    ((grupo.Descricao == null || grupo.Descricao == "") || (w.Descricao.Contains(grupo.Descricao)) &&
                    ((!grupo.ativoChanged) || (grupo.ativo == w.Ativo))
                )).ToList().Select(s => grupo.CreateGrupo(s)).ToList();
            return especialidades;
        }

        public bool AddUser(Login login)
        {
            bool result = false;
            Transaction.Begin((entity) =>
            {
                var grupo = entity.Grupo.FirstOrDefault(f => f.GrupoId == this.GrupoId);
                if (grupo == null)  
                    return false;
                var _login = entity.Login.FirstOrDefault(f => f.LoginId == login.LoginId);
                if (_login == null)
                    return false;
                if (grupo.Login.Any(a => a.LoginId == login.LoginId))
                    throw new Exception("Login já cadastrado para este grupo");
                grupo.Login.Add(_login);
                return true;
            }).OnSuccess(() =>
            {
                result = true;
            }).OnError(ex =>
            {
                throw ex;
                result = false;
            });
            return result;
        }

        public bool RemoveUser(Login login)
        {
            bool result = false;
            Transaction.Begin((entity) =>
            {
                var grupo = entity.Grupo.FirstOrDefault(f => f.GrupoId == this.GrupoId);
                if (grupo == null)
                    return false;
                var _login = entity.Login.FirstOrDefault(f => f.LoginId == login.LoginId);
                if (_login == null)
                    return false;
                grupo.Login.Remove(_login);
                return true;
            }).OnSuccess(() =>
            {
                result = true;
            }).OnError(ex =>
            {
                throw ex;
            });
            return result;
        }

        public bool Excluir()
        {
            bool result = false;
            Transaction.Begin((entity) =>
            {
                var grupo = entity.Grupo.FirstOrDefault(f => f.GrupoId == this.GrupoId);
                if (grupo == null)
                    throw new Exception("Grupo inválido");

                entity.Grupo.DeleteObject(grupo);
                return true;
            }).OnSuccess(() =>
            {
                result = true;
            }).OnError(ex =>
            {
                result = false;
            });
            return result;
        }
        
        public bool RemoveItem(ItemSistema itemSistema)
        {
            bool result = false;
            Transaction.Begin((entity) =>
            {
                if (itemSistema == null)
                    throw new Exception("Item inválido");
                var item = entity.ItemGrupo.FirstOrDefault(f => f.GrupoId == this.GrupoId && itemSistema.ItemId == f.ItemId);
                if (item == null)
                    throw new Exception("Item não associado ao grupo informado.");
                
                entity.ItemGrupo.DeleteObject(item);
                return true;
            }).OnSuccess(() =>
            {
                result = true;
            }).OnError(ex =>
            {
                throw ex;
            });
            return result;
        }

        public bool AddItem(ItemSistema itemSistema)
        {
            bool result = false;
            Transaction.Begin((entity) =>
            {
                if (itemSistema == null)
                    throw new Exception("Item inválido");
                if (entity.ItemGrupo.Any(a => a.ItemId == itemSistema.ItemId && this.GrupoId == a.GrupoId))
                    throw new Exception("Item já cadastrado para este grupo");
                var item = entity.ItemSistema.FirstOrDefault(f => f.ItemId == itemSistema.ItemId);
                if (item == null)
                    throw new Exception("Item não cadastrado no sistema");
                entity.AddToItemGrupo(new ItemGrupo()
                {
                    GrupoId = this.GrupoId,
                    ItemId = itemSistema.ItemId
                });
                return true;
            }).OnSuccess(() =>
            {
                result = true;
            }).OnError(ex =>
            {
                throw ex;
            });
            return result;
        }
    }
}